package server;

import java.io.*;  
import java.net.Socket;
import java.util.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 

import com.oreilly.servlet.RemoteDaemonHttpServlet;

public class ChatServlet extends RemoteDaemonHttpServlet implements ChatServer {
	// source acts as the distributor of new messages 
	MessageSource source = new MessageSource();

	// doGet() returns the next message. It blocks until there is one. 
	public void doGet(HttpServletRequest req, HttpServletResponse res) 
					throws ServletException, IOException { 
		res.setContentType("text/plain"); 
		PrintWriter out = res.getWriter(); 
		// Return the next message (blocking) 
		out.println(getNextMessage()); 
//
//		out.println("<html><head><title>Chat</title></head><body><applet code=" +
//				"\"client/HttpChatApplet.class\" archive=\"chat.jar,cos.jar\" " +
//				"width=500 Height=500><param name=file value=\"/etc/inet/hosts\">" +
//				"</applet></jsp:plugin></body></html>");		
	}
	
	// doPost() accepts a new message and broadcasts it to all 
	// the currently listening HTTP and socket clients. 
	public void doPost(HttpServletRequest req, HttpServletResponse res) 
	throws ServletException, IOException { 
		res.setContentType("text/plain");
		// Accept the new message as the "message" parameter 
		String message = req.getParameter("message");
		// Broadcast it to all listening clients 
		if (message != null) broadcastMessage(message); 
		// Set the status code to indicate there will be no response 
		res.setStatus(HttpServletResponse.SC_NO_CONTENT); 
	}
	
	// getNextMessage() returns the next new message. // It blocks until there is one. 
	public String getNextMessage() { 
		// Create a message sink to wait for a new message from the message source. 
		return new MessageSink().getNextMessage(source); 
		}
	
	 // broadcastMessage() informs all currently listening clients that there 
	// is a new message. Causes all calls to getNextMessage() to unblock. 
	public void broadcastMessage(String message) { 
		// Send the message to all the HTTP-connected clients by giving the 
		// message to the message source 
		source.sendMessage(message);
		} 
	
	// MessageSource acts as the source for new messages. 
	// Clients interested in receiving new messages can 
	// observe this object. 
	
	class MessageSource extends Observable { 
		public void sendMessage(String message) { 
			setChanged(); 
			notifyObservers(message); 
		} 
	}
	
	// MessageSink acts as the receiver of new messages. 
	// It listens to the source. 
	class MessageSink implements Observer {
		String message = null; 
		// set by update() and read by getNextMessage() 
		// Called by the message source when it gets a new message 
		synchronized public void update(Observable o, Object arg) {
			// Get the new message 
			message = (String)arg; 
			// Wake up our waiting thread 
			notify(); 
		} 
		// Gets the next message sent out from the message source 
		synchronized public String getNextMessage(MessageSource source) { 
			// Tell source we want to be told about new messages 
			source.addObserver(this); 
			// Wait until our update() method receives a message 
			while (message == null) { 
				try { 
					wait(); 
				} catch (Exception ignored) { 
						
				} 
			} 
			// Tell source to stop telling us about new messages 
			source.deleteObserver(this); 
			// Now return the message we received 
			// But first set the message instance variable to null 
			// so update() and getNextMessage() can be called again. 
			String messageCopy = message; 
			message = null; 
			return messageCopy; 
		} 
	}

	@Override
	public void handleClient(Socket arg0) {
		// TODO Auto-generated method stub
		
	}
}
